using System;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;

namespace Curchy.PERTToolbox.PropertyGrid
{
	/// <summary>
	/// PictureContextMenu is a specialized ContextMenu that is used to provide Cut/Copy/Paste functionalty
	/// for Images which a PictureBox or a DataPicture
	/// </summary>
	/// 
	[
	ToolboxBitmap(typeof(PictureBoxContextMenu))
	]
	public class PictureBoxContextMenu : System.Windows.Forms.ContextMenu
	{

		#region Public Events

		/// <summary>
		/// Raised when the Image property is changed
		/// </summary>
		public event EventHandler ImageChanged;
		
		#endregion

		#region Public Properties
		/// <summary>
		/// Return a 1 by 1 placeholder bitmap to use when none exists
		/// </summary>
		public static Bitmap EmptyBitmap
		{
			get
			{
					return sEmptyBitmap;
			}
		}

		/// <summary>
		/// Prevent the MenuItems property being used by the user when editing properties
		/// </summary>
		[
		Browsable(false),
		DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
		]
		new public System.Windows.Forms.Menu.MenuItemCollection MenuItems
		{
			get
			{
				throw new InvalidOperationException(cPropertyUnavailable);
			}
			set
			{
				throw new InvalidOperationException(cPropertyUnavailable);
			}
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Initialize a new copy of the PictureBoxContextMenu component and place it in a container
		/// </summary>
		/// <param name="container">The container to which to add this component</param>
		public PictureBoxContextMenu(System.ComponentModel.IContainer container)
		{
			container.Add(this);
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
		}

		/// <summary>
		/// Initialize a new copy of the PictureBoxContextMenu component
		/// </summary>
		public PictureBoxContextMenu()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
		}

		#endregion

		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		/// 
		// TODO: We're not showing shortcuts at the moment, because Picture Box can't receive the focus
		// so keyboard input to it is not possible
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(PictureBoxContextMenu));
			this.imageList1 = new System.Windows.Forms.ImageList(this.components);
			this.Cut = new System.Windows.Forms.MenuItem();
			this.Copy = new System.Windows.Forms.MenuItem();
			this.Paste = new System.Windows.Forms.MenuItem();
			this.PasteFrom = new System.Windows.Forms.MenuItem();
			this.Delete = new System.Windows.Forms.MenuItem();
			this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
			// 
			// imageList1
			// 
			this.imageList1.ImageSize = new System.Drawing.Size(16, 16);
			this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream")));
			this.imageList1.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// Cut
			// 
			this.Cut.Index = 0;
			this.Cut.Shortcut = System.Windows.Forms.Shortcut.CtrlX;
			this.Cut.ShowShortcut = false;
			this.Cut.Text = "Cut";
			this.Cut.Click += new System.EventHandler(this.menuItemClick);
			// 
			// Copy
			// 
			this.Copy.Index = 1;
			this.Copy.Shortcut = System.Windows.Forms.Shortcut.CtrlC;
			this.Copy.ShowShortcut = false;
			this.Copy.Text = "Copy";
			this.Copy.Click += new System.EventHandler(this.menuItemClick);
			// 
			// Paste
			// 
			this.Paste.Index = 2;
			this.Paste.Shortcut = System.Windows.Forms.Shortcut.CtrlV;
			this.Paste.ShowShortcut = false;
			this.Paste.Text = "Paste";
			this.Paste.Click += new System.EventHandler(this.menuItemClick);
			// 
			// PasteFrom
			// 
			this.PasteFrom.Index = 3;
			this.PasteFrom.Shortcut = System.Windows.Forms.Shortcut.CtrlV;
			this.PasteFrom.ShowShortcut = false;
			this.PasteFrom.Text = "Paste From ...";
			this.PasteFrom.Click += new System.EventHandler(this.menuItemClick);
			// 
			// Delete
			// 
			this.Delete.Index = 4;
			this.Delete.Shortcut = System.Windows.Forms.Shortcut.Del;
			this.Delete.ShowShortcut = false;
			this.Delete.Text = "Delete";
			this.Delete.Click += new System.EventHandler(this.menuItemClick);
			// 
			// openFileDialog1
			// 
			this.openFileDialog1.Filter = "All image files(*.bmp,*.gif,*.jpg,*.png,*.ico,*.emf,*.wmf)|*.bmp;*.gif;*.jpg;*.pn" +
				"g;*.ico;*.emf;*.wmf|Bitmap files(*.bmp,*.gif,*.jpg,*.png,*.ico)|*.bmp;*.gif;*.jp" +
				"g;*.png;*.ico|Metafiles(*.emf,*.wmf)|*.emf;*.wmf";
			// 
			// PictureBoxContextMenu
			// 
			base.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																			this.Cut,
																			this.Copy,
																			this.Paste,
																			this.PasteFrom,
																			this.Delete});

		}
		#endregion

		#region Overidden Functionality
		/// <summary>
		/// Raise the popup event. This is overriden to set the enablement of each menu item appropiately
		/// depending on the contents of the clipboard and of the Image property
		/// </summary>
		/// <param name="e">Contains the event data</param>
		protected override void OnPopup(EventArgs e)
		{
			base.OnPopup (e);

			Image bm= Image;

			if (bm==sEmptyBitmap)
				bm=null;
			IDataObject dataObj= Clipboard.GetDataObject();

			Cut.Enabled= (bm!=null);
			Copy.Enabled= (bm!=null);
			Paste.Enabled= (dataObj!=null) && dataObj.GetDataPresent(DataFormats.Bitmap);
			
			Delete.Enabled= (bm!=null);
			PasteFrom.Enabled= true;
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#endregion Overriden Functionality

		#region Private Functionality

		/// <summary>
		/// Gets or Sets the Image displayed by the container that popped up this context menu
		/// </summary>
		private Image Image
		{
			get
			{
				Image bm= null;
				IImageContainer imageContainer= this.SourceControl as IImageContainer;
				if (imageContainer!=null)
					bm= imageContainer.Image;
				else
				{
					PictureBox pictureBox= this.SourceControl as PictureBox;
					if (pictureBox!=null)
						bm= pictureBox.Image;
				}
				return bm;
			}
			set
			{
				IImageContainer imageContainer= this.SourceControl as IImageContainer;
				if (imageContainer!=null)
					imageContainer.Image= value;
				else
				{
					PictureBox pictureBox= this.SourceControl as PictureBox;
					if (pictureBox!=null)
						pictureBox.Image= value;
				}
				if (this.ImageChanged!=null)
					this.ImageChanged(this,EventArgs.Empty);
			}
		}

		/// <summary>
		/// Handle a click on an item in this context menu to perform one of Cut,Copy,Paste or PasteFrom
		/// </summary>
		/// <param name="sender">The sender of the event</param>
		/// <param name="e">Contains the event data</param>
		private void menuItemClick(object sender, EventArgs e)
		{
			Image bm= Image;
			// if (bm==null)
			//	return;

			if (sender==Cut || sender==Copy)
			{
				if (bm!=null)
					Clipboard.SetDataObject(bm,false);
			}
			if (sender!=Copy && sender!=PasteFrom)
			{
				// if (bm!=null)
				//	bm.Dispose();
				Image= sEmptyBitmap;
			}
			if (sender==Paste)
			{
				IDataObject dataObj= Clipboard.GetDataObject();
				Bitmap newbm= (Bitmap)dataObj.GetData(DataFormats.Bitmap);
				Image= newbm;
			}
			else if (sender==PasteFrom)
			{
				if (this.openFileDialog1.ShowDialog()==DialogResult.OK)
				{
					try
					{
						System.Drawing.Image newbm= Bitmap.FromFile(this.openFileDialog1.FileName);
						// if (bm!=null)
						//  	bm.Dispose();
						Image= newbm;
					}
					catch (Exception)
					{
					}
				}
			}

		}
		
		/// <summary>
		/// Not used currently, but intended to support left margin images.
		/// </summary>
		private System.Windows.Forms.ImageList imageList1; 
		/// <summary>
		/// MenuItem to support the Cut action
		/// </summary>
		private System.Windows.Forms.MenuItem Cut;
		/// <summary>
		/// MenuItem to support the Copy action
		/// </summary>
		private System.Windows.Forms.MenuItem Copy;
		/// <summary>
		/// MenuItem to support the Paste action
		/// </summary>
		private System.Windows.Forms.MenuItem Paste;
		/// <summary>
		/// MenuItem to support the PasteFrom action
		/// </summary>
		private System.Windows.Forms.MenuItem PasteFrom;
		/// <summary>
		/// MenuItem to support the Delete action
		/// </summary>
		private System.Windows.Forms.MenuItem Delete;
		/// <summary>
		/// An OpenFileDialog used by the PasteFrom action
		/// </summary>
		private System.Windows.Forms.OpenFileDialog openFileDialog1;
		/// <summary>
		/// Used whenever a bitmap is not available to avoid null references
		/// </summary>
		private static Bitmap sEmptyBitmap= new Bitmap(1,1);

		/// <summary>
		/// Created by the designer
		/// </summary>
		private System.ComponentModel.IContainer components;

		/// <summary>
		/// Error message that could be moved into a resource file to support internationalization
		/// </summary>
		const string cPropertyUnavailable= "This property cannot be accessed";

		#endregion Private Functionality
	}
	
	/// <summary>
	/// An interface that can be supported by any control that contains an image
	/// </summary>
	public interface IImageContainer
	{
		/// <summary>
		/// Allow the getting and setting of the Image in the container.
		/// </summary>
		Image Image { get; set; }
	}

}
